package com.gql.streamAPI;

import com.gql.methodReferences.Employee;
import com.gql.methodReferences.EmployeeData;
import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**
 * description: Stream中间操作
 * @author: gql
 * @date: 2022/04
 */
public class MiddleOperationTest {

    /**
     * 1. 筛选与切片
     */
    @Test
    public void fillterTest() {
        List<Employee> employeeList = EmployeeData.getEmployees();

        // 过滤(员工的工资大于7000的记录)
        employeeList.stream().filter(e -> e.getSalary() > 7000).forEach(System.out::println);
        System.out.println("*************************************************");

        // 截断(取前三天数据)
        employeeList.stream().limit(3).forEach(System.out::println);
        System.out.println("*************************************************");

        // 跳过(跳过前三条数据)
        employeeList.stream().skip(3).forEach(System.out::println);
        System.out.println("*************************************************");

        // 筛选(去重)
        employeeList.add(new Employee(1009, "强东", 34, 6000.38));
        employeeList.add(new Employee(1009, "强东", 34, 6000.38));
        employeeList.stream().distinct().forEach(System.out::println);
    }

    /**
     * 2.映射
     */
    @Test
    public void mapTest() {
        // map练习1 (将所有元素转换为大写)
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);

        // map练习2 (获取员工长度大于3的员工的姓名)
        List<Employee> employeeList = EmployeeData.getEmployees();
        employeeList.stream().map(Employee::getName).filter(name -> name.length() > 3).forEach(System.out::println);
        System.out.println();

        // flatMap
        //*************************map和flatMap的关系 == add和addAll的关系*************************👇
        ArrayList list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);

        ArrayList list2 = new ArrayList<>();
        list2.add(4);
        list2.add(5);
        list2.add(6);

        // add添加后list1有4个元素;addAll添加有6个元素
        list1.add(list2);
        //list1.addAll(list2);
        list1.forEach(System.out::println);
        //*************************map和flatMap的关系 == add和addAll的关系*************************👆
        System.out.println("*************************************************");

        // 相当于上面的add
        Stream<Stream<Character>> streamStream1 = list.stream().map(MiddleOperationTest::fromStringToStream);
        streamStream1.forEach(s -> s.forEach(System.out::println));
        System.out.println("*************************************************");

        // 相当于上面的addAll
        Stream<Character> streamStream2 = list.stream().flatMap(MiddleOperationTest::fromStringToStream);
        streamStream2.forEach(System.out::println);
    }

    /**
     * 将字符串中的多个字符构成的集合转换为对应的Stream对象
     * @param str
     * @return
     */
    public static Stream<Character> fromStringToStream(String str) {
        ArrayList<Character> list = new ArrayList<>();
        for (Character c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }


    /**
     * 3. 排序
     */
    @Test
    public void sortTest() {
        List<Integer> list = Arrays.asList(12, 34, 64, 1, -98, 66, 55, 88);
        //Collection面向内存
        //Collections.sort(list);
        //list.forEach(System.out::println);

        // Stream面向CPU
        list.stream().sorted().forEach(s -> {
            System.out.print(s + " ");
        });
        System.out.println();

        // Java层面涉及对象的排序就使用Comporator 自然排序和定制排序
        List<Employee> employeeList1 = EmployeeData.getEmployees();
        employeeList1.stream().sorted((e1, e2) -> {
            // 先按照年龄排序 desc
            int compare = Integer.compare(e2.getAge(), e1.getAge());
            if (compare != 0) {
                return compare;
            } else {
                // 再按照薪水 asc
                return Double.compare(e1.getSalary(), e2.getSalary());
            }
        }).forEach(System.out::println);
    }


}






